using System;
using System.Data;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;

using AIFSContentManagementSystem.Criteria;
using AIFSContentManagementSystem.Criteria.Messages;

using AIFSContentManagementSystem.ListExtensions;

namespace AIFSContentManagementSystem.Articles
{
    using Messages;

    public sealed class ArticleService : IArticleService
    {
        #region IArticleManager Members

        IRepositoryMap repositoryMap;
        IParser parser;

        public ArticleService(IRepositoryMap RepositoryMap, IParser Parser)
        {
            this.repositoryMap = RepositoryMap;
            parser = Parser;
        }

        public GetFilteredArticleListResponse Process(GetFilteredArticleListRequest request)
        {            
            GetFilteredArticleListResponse response = new GetFilteredArticleListResponse();

            if (request.ProgramName == null)
                response.AddErrorMessage("Program name is required");

            if (request.ArticleType == ArticleType.UNSET)
                response.AddErrorMessage("Article type is required");

            if (response.HasError)
                return response;

            //Step 1 get the article entity
            IArticleRepository articleRepository = this.repositoryMap.Get<IArticleRepository>();
            List<Article> articles = articleRepository.GetArticles(Enum.GetName(typeof(ArticleType), request.ArticleType), request.ProgramName, request.FlaggedAsActive);

            if (articles != null && articles.Count == 0)
            {
                return response;
            }

            //Create an ListWithEvents to "fire" onaddnew event for parsing
            ListWithEvents<Article> filteredArticles = new ListWithEvents<Article>();
            filteredArticles.OnAddNewItem += new AddNewToListWithEvents<Article>(filteredArticles_OnAddNewItem);

            //If request did not have any criterion filter return all articles retrieved
            if (request.Criteria == null)
            {
                filteredArticles.Add(articles);
            }
            else
            {
                foreach (Article article in articles)
                {
                    //Assert the criteria with the requested criteria, if it matches add to the filtered list
                    bool assertResult = false;

                    //combine the request article criterion and the or criterion.
                    assertResult = article.IsMatch(request.Criteria);

                    //Add to the filtered list. At this point it is ready to be parsed
                    if (assertResult)
                    {
                        filteredArticles.Add(article);
                    }
                }
            }

            response.AddArticle(filteredArticles);

            return response;
        }

        private void filteredArticles_OnAddNewItem(object sender, AddNewToListEventArgs<Article> e)
        {
            if(e.NewObject != null && parser != null)
                parser.Parse(e.NewObject);
        }

        #endregion        
    }
}
